﻿using SmartPlant.Core.Mvvm;
using System.Collections;
using System.Collections.Specialized;
using System.Windows;
using Telerik.Windows.Controls;

namespace SmartPlant.Core.Behavior
{
    /// <summary>
    /// Columns
    /// </summary>
    public class TelerikColumnsBindingBehavior : SmartViewModel
    {
        private readonly RadGridView _grid = null;
        private readonly INotifyCollectionChanged _columns = null;

        public static readonly DependencyProperty ColumnsProperty
            = DependencyProperty.RegisterAttached("Columns", typeof(INotifyCollectionChanged), typeof(TelerikColumnsBindingBehavior),
                new PropertyMetadata(new PropertyChangedCallback(OnColumnsPropertyChanged)));

        public static void SetColumns(DependencyObject dependencyObject, INotifyCollectionChanged columns)
        {
            dependencyObject.SetValue(ColumnsProperty, columns);
        }

        public static INotifyCollectionChanged GetColumns(DependencyObject dependencyObject)
        {
            return (INotifyCollectionChanged)dependencyObject.GetValue(ColumnsProperty);
        }

        private static void OnColumnsPropertyChanged(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs e)
        {
            var grid = dependencyObject as RadGridView;
            var columns = e.NewValue as INotifyCollectionChanged;

            if (grid != null && columns != null)
            {
                var behavior = new TelerikColumnsBindingBehavior(grid, columns);
                behavior.Attach();
            }
        }

        private void Attach()
        {
            if (_grid != null && _columns != null)
            {
                Transfer(GetColumns(_grid) as IList, _grid.Columns);

                _columns.CollectionChanged -= ContextColumns_CollectionChanged;
                _columns.CollectionChanged += ContextColumns_CollectionChanged;
            }
        }

        public TelerikColumnsBindingBehavior(RadGridView grid, INotifyCollectionChanged columns)
        {
            this._grid = grid;
            this._columns = columns;
        }

        void ContextColumns_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
        {
            UnsubscribeFromEvents();

            Transfer(GetColumns(_grid) as IList, _grid.Columns);

            SubscribeToEvents();
        }

        void GridColumns_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
        {
            UnsubscribeFromEvents();

            Transfer(_grid.Columns, GetColumns(_grid) as IList);

            SubscribeToEvents();
        }

        private void SubscribeToEvents()
        {
            _grid.Columns.CollectionChanged += GridColumns_CollectionChanged;

            if (GetColumns(_grid) != null)
            {
                GetColumns(_grid).CollectionChanged += ContextColumns_CollectionChanged;
            }
        }

        private void UnsubscribeFromEvents()
        {
            _grid.Columns.CollectionChanged -= GridColumns_CollectionChanged;

            if (GetColumns(_grid) != null)
            {
                GetColumns(_grid).CollectionChanged -= ContextColumns_CollectionChanged;
            }
        }

        public static void Transfer(IList source, IList target)
        {
            if (source == null || target == null)
                return;

            target.Clear();

            foreach (object o in source)
            {
                target.Add(o);
            }
        }
    }
}
